package spring.fox.processor;


import spring.fox.annotation.RpcService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanClassLoaderAware;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.ResourceLoaderAware;
import org.springframework.core.env.Environment;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.type.filter.AnnotationTypeFilter;
import org.springframework.util.CollectionUtils;
import spring.fox.scanner.RpcServiceAnnotationClassPathDefinitionScanner;

import java.util.Arrays;
import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.Set;

/**
 * @author cuichao
 * @Description: RpcServiceBeanDefinitionRegisteredProcessor
 * @Date: create in 2021/3/3 12:46
 */
public class RpcServiceBeanDefinitionRegisteredProcessor implements BeanDefinitionRegistryPostProcessor, ResourceLoaderAware, BeanClassLoaderAware, EnvironmentAware {

    private final Logger logger = LoggerFactory.getLogger(getClass());

    private Environment environment;

    private ClassLoader classLoader;

    private ResourceLoader resourceLoader;

    private String rpcApplicationName;

    private final Set<String> packagesToScan;


    public RpcServiceBeanDefinitionRegisteredProcessor(String... packagesToScan) {
        this(Arrays.asList(packagesToScan));
    }

    public RpcServiceBeanDefinitionRegisteredProcessor(Collection<String> packagesToScan) {
        this(new LinkedHashSet<>(packagesToScan));
    }

    public RpcServiceBeanDefinitionRegisteredProcessor(Set<String> packagesToScan) {
        this.packagesToScan = packagesToScan;
    }


    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
        if (!CollectionUtils.isEmpty(packagesToScan)) {
            registryRpcService(packagesToScan, registry);
        } else {
            if (logger.isWarnEnabled()) {
                logger.warn("packagesToScan is empty , Rpc-Service-Bean registry will be ignored!");
            }
        }
    }

    /**
     * 注册Rpc服务BeanDefinition
     *
     * @param packagesToScan
     * @param registry
     */
    private void registryRpcService(Set<String> packagesToScan, BeanDefinitionRegistry registry) {
        //构建扫描器
        RpcServiceAnnotationClassPathDefinitionScanner scanner = new RpcServiceAnnotationClassPathDefinitionScanner(registry, classLoader ,environment);
        scanner.setEnvironment(environment);
        scanner.setResourceLoader(resourceLoader);
        //添加需要注册的Service
        scanner.addIncludeFilter(new AnnotationTypeFilter(RpcService.class));
        //扫描生成definition
        for (String packageToScan : packagesToScan) {
            scanner.scan(packageToScan);
        }
    }


    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        //nothing to  do
    }


    @Override
    public void setResourceLoader(ResourceLoader resourceLoader) {
        this.resourceLoader = resourceLoader;
    }


    @Override
    public void setBeanClassLoader(ClassLoader classLoader) {
        this.classLoader = classLoader;
    }

    @Override
    public void setEnvironment(Environment environment) {
        this.environment = environment;
    }
}
